﻿// MIT License
// 开源地址：https://gitee.com/co1024/AbcMvc
// Copyright (c) 2021-2022 1024
// Abc.Mvc=Furion+EF+SqlSugar+Pear layui admin.

using ERAS.Core.SeedData;
using Furion.DynamicApiController;

namespace Abc.Application.HtAdminServices;

/// <summary>
/// 开发服务
/// </summary>
[ApiDescriptionSettings("HtAdmin", Name = "HtDeveloper")]
[AuthorityController(area: "API", controller: "HtDeveloper", controllerDescription: "开发服务", PCode = "API")]
public class HtDeveloperService : IDynamicApiController
{
    private readonly ILogger<HtDeveloperService> _logger;

    private readonly ISqlSugarClient _db;

    public HtDeveloperService(ILogger<HtDeveloperService> logger
    , ISqlSugarClient db)
    {
        _logger = logger;
        _db = db;
    }

    #region 更新菜单功能权限

    /// <summary>
    /// 更新菜单功能权限
    /// </summary>
    /// <returns></returns>
    [UnitOfWork]
    [MaPermission(name: "更新菜单功能权限", actions: "UpdateMenuPermission")]
    public async Task UpdateMenuPermission()
    {
        //查询自动生成的菜单

        var mvcPermissions = AuthorityHelper.GetMvcPermissions();
        var apiPermissions = AuthorityHelper.GetApiPermissions();

        //获取数据库中全部的菜单和权限
        var dbmenus = await _db.Queryable<SysMenu>().ToListAsync();

        var dbareas = dbmenus.Where(o => !string.IsNullOrWhiteSpace(o.Area)).Select(o => o.Area).Distinct();
        var mvcareas = mvcPermissions.Select(o => o.Area).Distinct();
        var apiareas = apiPermissions.Select(o => o.Area).Distinct();

        var AddMenus = new List<SysMenu>();

        HandleMenuArea(dbmenus, mvcareas, AddMenus);
        HandleMenuArea(dbmenus, apiareas, AddMenus);

        var DeleteMenus = new List<SysMenu>();
        //MVC : 移除 数据库中不存在的MVC 菜单
        RemoveDbNotData(mvcPermissions, dbmenus, MenuArea.Mvc, DeleteMenus);

        // API :移除 数据库中不存在的API数据
        RemoveDbNotData(apiPermissions, dbmenus, MenuArea.API, DeleteMenus);

        //MVC： 新增或更新 菜单与权限
        AddOrUpdateMenu(mvcPermissions, dbmenus, AddMenus, MenuArea.Mvc);
        //API： 新增或更新 菜单与权限
        AddOrUpdateMenu(apiPermissions, dbmenus, AddMenus, MenuArea.API);

        //获取菜单目录
        foreach (var menu in SysMenuSeedData.Data())
        {
            if (dbmenus.Any(o => o.Code.Trim().ToLower() == menu.Code.Trim().ToLower())) continue;
            menu.Id = 0;
            AddMenus.Add(menu);
        }

        foreach (var addmenu in AddMenus)
        {
            addmenu.IsAutoGeneration = true;
        }

        //验证Code 是否有重复
        foreach (var code in AddMenus.Select(o => o.Code.Trim().ToLower()).Distinct())
        {
            if (AddMenus.Count(o => o.Code.Trim().ToLower() == code) > 1)
            {
                throw Oops.Bah(errorMessage: $"Code：{code} 重复，请检查!!");
            }
        }
        var deleteMenuIds = DeleteMenus.Select(o => o.Id).ToList();
        //删除不存在的数据
        await _db.Deleteable<SysMenu>().Where(o => deleteMenuIds.Contains(o.Id)).ExecuteCommandAsync();
        //新增菜单数据
        await _db.Insertable<SysMenu>(AddMenus).ExecuteCommandAsync();
    }

    /// <summary>
    /// 处理菜单 Area
    /// </summary>
    /// <param name="dbmenus"></param>
    /// <param name="areas"></param>
    /// <param name="addMenus"></param>
    private void HandleMenuArea(List<SysMenu> dbmenus, IEnumerable<string> areas, List<SysMenu> addMenus)
    {
        foreach (var area in areas)
        {
            if (dbmenus.Any(o => string.IsNullOrWhiteSpace(o.PCode) && o.Code.ToLower() == area.ToLower() && o.Area.ToLower() == area.ToLower())) continue;
            var menu = new SysMenu
            {
                Area = area.Trim(),
                Code = area.Trim(),
                Name = area.Trim(),
                IsEnable = true,
                IsSystem = true,
                IsShow = true,
                MenuType = MenuType.目录
            };
            addMenus.Add(menu);
        }
    }

    /// <summary>
    /// 移除数据库中不存在的数据
    /// </summary>
    /// <param name="menuItems"></param>
    /// <param name="dbmenus">数据库中菜单</param>
    /// <param name="menuArea">菜单区域/分类</param>
    /// <param name="deleteMenus">删除的菜单集合</param>
    private void RemoveDbNotData(List<AuthorityMenuItem> menuItems, List<SysMenu> dbmenus, MenuArea menuArea, List<SysMenu> deleteMenus)
    {
        var dbmenus2 = dbmenus.Where(o => o.MenuArea == menuArea && o.IsAutoGeneration && (o.MenuType == MenuType.菜单 || o.MenuType == MenuType.功能方法 || o.MenuType == MenuType.API));
        //生成的所有Code
        var dic = new Dictionary<string, string>();
        foreach (var menuitem in menuItems)
        {
            if (dic.ContainsKeyIgnoreCase(menuitem.Code))
            {
                foreach (var item in menuitem.Permissions)
                {
                    if (dic.ContainsKeyIgnoreCase(item.Code)) continue;
                    dic.Add(item.Code, item.Code);
                }
            }
            else
            {
                dic.Add(menuitem.Code, menuitem.Code);
                foreach (var item in menuitem.Permissions)
                {
                    if (dic.ContainsKeyIgnoreCase(item.Code)) continue;
                    dic.Add(item.Code, item.Code);
                }
            }
        }

        //遍历移除数据库中所有生成的不存在的菜单数据
        foreach (var menuid in dbmenus2.Where(o => o.MenuType == MenuType.目录 || o.MenuType == MenuType.菜单).Select(o => o.Id).ToList())
        {
            var dbmenu = dbmenus2.First(o => o.Id == menuid);
            if (string.IsNullOrWhiteSpace(dbmenu.Code)) continue;

            if (!dic.ContainsKeyIgnoreCase(dbmenu.Code))
            {
                deleteMenus.Add(dbmenu);
            }
        }
    }

    /// <summary>
    /// 新增或更新菜单、功能
    /// </summary>
    /// <param name="menuItems"></param>
    /// <param name="dbmenus"></param>
    /// <param name="addMenus"></param>
    /// <param name="menuArea"></param>
    private void AddOrUpdateMenu(List<AuthorityMenuItem> menuItems, List<SysMenu> dbmenus, List<SysMenu> addMenus, MenuArea menuArea)
    {
        foreach (var menuitem in menuItems)
        {
            var dbmenu = dbmenus.FirstOrDefault(o => o.MenuArea == menuArea && o.Code.Trim().ToLower() == menuitem.Code.Trim().ToLower());
            if (dbmenu == null)
            {
                dbmenu = menuitem.Adapt<SysMenu>();
                dbmenu.MenuArea = menuArea;
                dbmenu.IsEnable = true;
                dbmenu.Sort = 0;
                dbmenu.OpenType = 0;
                dbmenu.IsShow = true;
                //menu.MenuType = MenuType.菜单;
                if (!string.IsNullOrWhiteSpace(menuitem.CreateDate))
                {
                    dbmenu.CreationTime = Convert.ToDateTime(menuitem.CreateDate);
                }
                addMenus.Add(dbmenu);

                foreach (var permissionitem in menuitem.Permissions)
                {
                    var dbpermission = dbmenus.FirstOrDefault(o => o.Code.Trim().ToLower() == permissionitem.Code.Trim().ToLower());
                    if (dbpermission == null)
                    {
                        var addpermission = permissionitem.Adapt<SysMenu>();
                        //addpermission.MenuType = MenuType.功能方法;
                        addpermission.Icon = "layui-icon-right";
                        addpermission.MenuArea = menuArea;
                        addpermission.Area = dbmenu.Area;
                        addpermission.PCode = dbmenu.Code;
                        addpermission.IsEnable = true;
                        addpermission.Sort = 0;
                        addpermission.OpenType = 0;
                        addpermission.IsShow = true;
                        if (!string.IsNullOrWhiteSpace(menuitem.CreateDate))
                        {
                            addpermission.CreationTime = Convert.ToDateTime(menuitem.CreateDate);
                        }
                        addMenus.Add(addpermission);
                    }
                    else
                    {
                        //更新以存在的功能
                        dbpermission.Controller = permissionitem.Controller;
                        dbpermission.Name = permissionitem.Name;
                        dbpermission.Actions = permissionitem.Actions;
                        dbpermission.PCode = dbmenu.Code;
                        dbpermission.MenuArea = menuArea;
                        dbpermission.Url = permissionitem.Url;
                    }
                }
            }
            else
            {
                //菜单已存在，
                {
                    if (string.IsNullOrWhiteSpace(menuitem.PCode))
                    {
                        dbmenu.PCode = menuitem.PCode;
                    }
                    dbmenu.Area = menuitem.Area;
                    dbmenu.Name = menuitem.Name;
                    dbmenu.Url = menuitem.Url;
                    dbmenu.IsDisuse = menuitem.IsDisuse;
                    dbmenu.PCode = menuitem.PCode;
                    dbmenu.IsShow = menuitem.IsShow;
                }

                var dbmenus2 = dbmenus.Where(o => o.IsAutoGeneration && o.MenuArea == menuArea && (o.MenuType == MenuType.功能方法 || o.MenuType == MenuType.API));
                //删除不存在的功能
                {
                    foreach (var permissionid in dbmenus2.Select(o => o.Id).ToList())
                    {
                        var dbpermission = dbmenus2.First(o => o.Id == permissionid);

                        if (menuitem.Code.Trim().ToLower() == dbpermission.PCode.Trim().ToLower() && menuitem.Permissions.All(o => o.Code.Trim().ToLower() != dbpermission.Code.Trim().ToLower()))
                        {
                            dbmenus.Remove(dbpermission);
                        }
                    }
                }
                //添加新的功能
                {
                    foreach (var permissionitem in menuitem.Permissions)
                    {
                        var dbpermission = dbmenus2.FirstOrDefault(o => o.Code.Trim().ToLower() == permissionitem.Code.Trim().ToLower());
                        if (dbpermission == null)
                        {
                            //数据库中不存在，新增
                            var addpermission = permissionitem.Adapt<SysMenu>();
                            //addpermission.MenuType = MenuType.功能方法;
                            addpermission.Icon = "layui-icon-right";
                            addpermission.MenuArea = menuArea;
                            if (!string.IsNullOrWhiteSpace(permissionitem.CreateDate))
                            {
                                addpermission.CreationTime = Convert.ToDateTime(permissionitem.CreateDate);
                            }
                            addpermission.PCode = dbmenu.Code;
                            addpermission.Area = menuitem.Area;
                            addMenus.Add(addpermission);
                        }
                        else
                        {
                            //数据库中存在，更新信息
                            //更新以存在的功能
                            dbpermission.Area = menuitem.Area;
                            dbpermission.Controller = permissionitem.Controller;
                            dbpermission.Name = permissionitem.Name;
                            dbpermission.Actions = permissionitem.Actions;
                            dbpermission.PCode = dbmenu.Code;
                            dbpermission.MenuArea = menuArea;
                            dbpermission.Url = permissionitem.Url;
                        }
                    }
                }
            }
        }
    }

    /// <summary>
    /// 删除数据库所有菜单
    /// </summary>
    /// <returns></returns>
    [MaPermission(name: "删除数据库所有菜单", actions: "DeleteDbAllMenu")]
    public async Task DeleteDbAllMenu()
    {
        await _db.Deleteable<SysRoleMenu>().Where(o => o.MenuId > 0).ExecuteCommandAsync();
        await _db.Deleteable<SysMenu>().Where(o => o.Id > 0).ExecuteCommandAsync();
    }

    #endregion 更新菜单功能权限

    /// <summary>
    /// RSA 加密解密验证
    /// </summary>
    /// <param name="publicKey">公钥</param>
    /// <param name="privateeKey">私钥</param>
    /// <returns></returns>
    public bool RsaVer(string publicKey, string privateeKey)
    {
        var LoginPriveKey = privateeKey.Replace("\r\n", "").Replace("\r", "").Replace("\n", "").RsaKeyFilter();
        var LoginPublicKey = publicKey.Replace("\r\n", "").Replace("\r", "").Replace("\n", "").RsaKeyFilter();
        LoginRsa rsa = new LoginRsa(LoginPriveKey, LoginPublicKey);
        //加密
        var enstr = rsa.Encrypt(publicKey);

        //解密
        var pwdtxt = rsa.Decrypt(enstr);

        return true;
    }
}